package controllers

import (
	"encoding/json"
	"net/http"

	"fmt"

	"github.com/gin-contrib/sessions"
	"github.com/gin-gonic/gin"
	"github.com/github-user/TokTik/helper"
	"github.com/github-user/TokTik/models"
	"gopkg.in/mgo.v2/bson"
)

type Response struct {
	Code    int         `bson:"code"`
	Type    string      `bson:"type"`
	Message interface{} `bson:"message"`
}

type UserInfoRes struct {
	Code  int
	State string
	Data  models.User
}

const (
	StatusSuccess  = "success"
	StatusBadReq   = "bad_req"
	StatusNotLogin = "not_login"
	StatusNotAllow = "not_allow"
	StatusExist    = "had_exist"
	StatusError    = "error"
	StatusNotValid = "not_invalid"
)

const (
	db         = "TokTik"
	collection = "user"
)

func Register(c *gin.Context) {

	var user models.RegisterReq
	err := json.NewDecoder(c.Request.Body).Decode(&user)
	if err != nil || user.Email == "" || user.Password == "" {
		c.JSON(http.StatusOK, &Response{
			Code:    400,
			Type:    "fail",
			Message: "",
		})
		return
	}
	err = models.Register(user.Name, user.Email, user.Password)
	if err != nil {
		c.JSON(http.StatusOK, &Response{
			Code:    400,
			Type:    "fail",
			Message: "",
		})
		return
	}
	c.JSON(http.StatusOK, &Response{
		Code: 200,
		Type: "success",
	})
}

func Login(c *gin.Context) {
	session := sessions.Default(c)
	option := sessions.Options{MaxAge: 3600 * 24, Path: "/"}
	session.Options(option)
	var user models.LoginReq
	err := json.NewDecoder(c.Request.Body).Decode(&user)
	if err != nil {
		fmt.Println(err)
		c.JSON(http.StatusOK, &Response{
			Code:    400,
			Type:    "fail",
			Message: "bad_eq",
		})
	}
	exist := models.IsExist(db, collection, bson.M{"email": user.Name})
	if exist {
		err = models.Login(user.Name, user.Password)
		if err != nil {
			c.JSON(http.StatusOK, &Response{
				Code:    400,
				Type:    "fail",
				Message: "username and password do not match",
			})
		} else {
			var u models.User
			models.FindOne(db, collection, bson.M{"email": user.Name}, nil, &u)
			fmt.Println(u.ID.Hex())
			session.Set("sessionid", u.ID.Hex())
			session.Save()
			///////////////
			//c.Writer.Header().Set("Accept-Ranges", "bytes")
			///////////////
			c.JSON(http.StatusOK, &Response{
				Code:    http.StatusOK,
				Type:    "success",
				Message: u.ID.Hex(),
			})
		}

	} else {
		c.JSON(http.StatusOK, &Response{
			Code:    400,
			Type:    "fail",
			Message: "the user not exist",
		})
	}
}

func Authorize() gin.HandlerFunc {
	return func(c *gin.Context) {
		session := sessions.Default(c)
		v := session.Get("sessionid")
		fmt.Println("cookie: ", v)
		if v != nil {
			// 验证通过，会继续访问下一个中间件
			c.Next()
		} else {
			// 验证不通过，不再调用后续的函数处理
			c.Abort()
			c.JSON(http.StatusUnauthorized, gin.H{"message": "访问未授权"})
			return
		}
	}
}

func GetSelfMessage(c *gin.Context) {
	session := sessions.Default(c)
	v := session.Get("sessionid")

	var u models.User
	models.FindOne(db, collection, bson.M{"_id": bson.ObjectIdHex(v.(string))}, nil, &u)
	c.JSON(http.StatusOK, &UserInfoRes{
		Code:  http.StatusOK,
		State: StatusSuccess,
		Data:  u,
	})
	//fmt.Println(u.Info.Name)
}

func ChangeMessage(c *gin.Context) {
	session := sessions.Default(c)
	v := session.Get("sessionid")
	var user models.User
	json.NewDecoder(c.Request.Body).Decode(&user)

	var u models.User
	models.FindOne(db, collection, bson.M{"_id": bson.ObjectIdHex(v.(string))}, nil, &u)
	if user.Info.Name != "" {
		u.Info.Name = user.Info.Name
	}
	if user.Email != "" {
		u.Email = user.Email
	}
	if user.Password != "" {
		var data []byte = []byte(user.Password)
		hashCode := helper.GetSHA256HashCode(data)
		u.Password = hashCode
	}
	if user.Info.Bio != "" {
		u.Info.Bio = user.Info.Bio
	}
	if user.Info.Avatar != "" {
		u.Info.Avatar = user.Info.Avatar
	}
	if user.Info.Gender == 1 {
		u.Info.Gender = 1
	}
	if user.Info.Gender == 0 {
		u.Info.Gender = 0
	}

	models.Update(db, collection, bson.M{"_id": bson.ObjectIdHex(v.(string))}, bson.M{"$set": bson.M{
		"email":    u.Email,
		"password": u.Password,
		"info":     u.Info,
	}})
	c.JSON(http.StatusOK, &Response{
		Code:    200,
		Type:    "success",
		Message: "",
	})
}

func GetUserMessageByID(c *gin.Context) {
	var u models.User
	var finfo models.FriendInfo
	models.FindOne(db, collection, bson.M{"_id": bson.ObjectIdHex(c.Param("id"))}, nil, &u)
	finfo.Avatar = u.Info.Avatar
	finfo.Bio = u.Info.Bio
	finfo.Email = u.Email
	finfo.Gender = u.Info.Gender
	finfo.Name = u.Info.Name
	c.JSON(http.StatusOK, &Response{
		Code:    200,
		Type:    "success",
		Message: finfo,
	})
}
